package com.beyondsoft.sabg.edu.service.dataanalysis.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.aliyun.dataanalysisgbi20240823.models.RunDataAnalysisRequest;
import com.aliyun.dataanalysisgbi20240823.models.RunDataAnalysisResponse;
import com.aliyun.teautil.models.RuntimeOptions;
import com.beyondsoft.sabg.edu.config.AnalysisConfig;
import com.beyondsoft.sabg.edu.model.dto.ChatRequest;
import com.beyondsoft.sabg.edu.service.dataanalysis.AnalysisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 * 析言服务实现类
 */
@Service
@Slf4j
public class AnalysisServiceImpl implements AnalysisService {

    @Autowired
    private com.aliyun.dataanalysisgbi20240823.Client analysisClient;

    @Autowired
    private AnalysisConfig analysisConfig;

    @Override
    public SseEmitter chatStream(ChatRequest request) throws Exception {
        log.info("开始智能对话流式返回，查询内容：{}", request.getQuery());
        SseEmitter emitter = new SseEmitter(300000L); // 5分钟超时
        
        CompletableFuture.runAsync(() -> {
            try {
                Map<String, Object> params = Map.of(
                        "enableChatMode", true,
                        "chartsFramework", "echarts"
                );

                // 构建请求
                RunDataAnalysisRequest analysisRequest = new RunDataAnalysisRequest()
                        .setAgentCtrlParams(params)
                        .setQuery(request.getQuery());
                
                // 处理dataRole - 如果为空或null，不设置该字段，默认为管理员权限
                if (request.getDataRole() != null && !request.getDataRole().isEmpty()) {
                    analysisRequest.setDataRole(request.getDataRole());
                }
                
                // 处理userParams - 如果为空或null，不设置该字段
                if (ObjectUtil.isNotEmpty(request.getUserParams())) {
                    analysisRequest.setUserParams(request.getUserParams());
                }
                
                // 如果有sessionId，则设置
                if (StrUtil.isNotBlank(request.getSessionId())) {
                    analysisRequest.setSessionId(request.getSessionId());
                }

                RuntimeOptions runtime = new RuntimeOptions();
                runtime.setConnectTimeout(30000);
                runtime.setReadTimeout(30000);
                runtime.setAutoretry(false);
                Map<String, String> headers = new HashMap<>();
                
                try {
                    RunDataAnalysisResponse response = analysisClient.runDataAnalysisWithOptions(
                            analysisConfig.getWorkspaceId(), analysisRequest, headers, runtime);
                    
                    // 如果没有异常，说明是同步响应
                    log.info("API调用成功，响应状态: {}", response.getStatusCode());
                    emitter.send(SseEmitter.event()
                        .name("success")
                        .data("智能对话任务已提交，请求ID：" + response.getBody().getData().getRequestId()));
                    emitter.complete();
                    
                } catch (Exception e) {
                    // 这里的异常实际包含了流式数据
                    String errorMessage = e.getMessage();
                    
                    if (errorMessage != null && errorMessage.contains("data:")) {
                        // 解析并实现打字机效果
                        simulateTypingEffect(errorMessage, emitter);
                    } else {
                        log.error("未找到流式数据，这是真正的错误: {}", errorMessage, e);
                        emitter.completeWithError(e);
                    }
                }
                
            } catch (Exception e) {
                log.error("智能对话流式返回失败: {}", e.getMessage(), e);
                try {
                    emitter.send(SseEmitter.event()
                        .name("error")
                        .data("智能对话失败：" + e.getMessage()));
                    emitter.completeWithError(e);
                } catch (IOException ioException) {
                    log.error("发送错误消息失败", ioException);
                }
            }
        });
        
        return emitter;
    }

    /**
     * 模拟打字机效果的流式传输
     */
    private void simulateTypingEffect(String streamData, SseEmitter emitter) {
        try {
            log.info("开始模拟打字机效果的流式传输...");
            
            // 首先尝试实现真正的流式传输
            if (implementRealStreamTransfer(streamData, emitter)) {
                log.info("✅ 真正的流式传输完成");
                return;
            }
            
            // 如果无法实现真正的流式传输，则提取最终文本进行打字机效果
            String fullText = extractFinalTextContent(streamData);
            if (fullText == null || fullText.length() < 10) {
                log.warn("无法提取有效文本内容，回退到原始流式转发");
                forwardOriginalStreamData(streamData, emitter);
                return;
            }
            
            log.info("提取到完整文本，长度: {}, 开始打字机效果传输", fullText.length());
            
            // 按字符逐个发送，模拟打字机效果
            StringBuilder currentText = new StringBuilder();
            int charsPerBatch = 2; // 每次发送2个字符
            int delayMs = 50; // 每批间隔50毫秒
            
            for (int i = 0; i < fullText.length(); i += charsPerBatch) {
                int endIndex = Math.min(i + charsPerBatch, fullText.length());
                String batch = fullText.substring(i, endIndex);
                currentText.append(batch);
                
                // 构造流式数据格式
                JSONObject eventData = new JSONObject();
                JSONObject header = new JSONObject();
                header.put("Event", "task-progress-generating");
                
                JSONObject payload = new JSONObject();
                JSONObject output = new JSONObject();
                output.put("Text", currentText.toString());
                payload.put("Output", output);
                
                eventData.put("Header", header);
                eventData.put("Payload", payload);
                
                // 发送数据
                emitter.send(SseEmitter.event()
                    .name("task-progress-generating")
                    .data(eventData.toString()));
                
                log.debug("发送打字机数据，当前长度: {}", currentText.length());
                
                // 延迟
                if (endIndex < fullText.length()) {
                    try {
                        Thread.sleep(delayMs);
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        log.warn("打字机效果被中断");
                        break;
                    }
                }
            }
            
            // 发送完成事件
            JSONObject finalEvent = new JSONObject();
            JSONObject finalHeader = new JSONObject();
            finalHeader.put("Event", "task-progress-completed");
            
            JSONObject finalPayload = new JSONObject();
            JSONObject finalOutput = new JSONObject();
            finalOutput.put("Text", fullText);
            finalPayload.put("Output", finalOutput);
            finalPayload.put("End", true);
            
            finalEvent.put("Header", finalHeader);
            finalEvent.put("Payload", finalPayload);
            
            emitter.send(SseEmitter.event()
                .name("task-progress-completed")
                .data(finalEvent.toString()));
            
            emitter.complete();
            log.info("✅ 打字机效果流式传输完成，总字符数: {}", fullText.length());
            
        } catch (Exception e) {
            log.error("打字机效果传输失败", e);
            try {
                emitter.completeWithError(e);
            } catch (Exception ex) {
                log.error("完成错误状态失败", ex);
            }
        }
    }
    
    /**
     * 实现真正的流式传输
     */
    private boolean implementRealStreamTransfer(String streamData, SseEmitter emitter) {
        try {
            String[] lines = streamData.split("\n");
            boolean hasValidData = false;
            
            for (String line : lines) {
                if (line.startsWith("data:")) {
                    String jsonData = line.substring(5);
                    try {
                        JSONObject data = JSONUtil.parseObj(jsonData);
                        
                        // 检查是否有有效的数据结构
                        if (data.containsKey("data")) {
                            JSONObject innerData = data.getJSONObject("data");
                            String event = innerData.getStr("event");
                            
                            if (event != null) {
                                hasValidData = true;
                                
                                // 根据事件类型处理不同的数据
                                switch (event) {
                                    case "rewrite":
                                        // 发送重写事件
                                        emitter.send(SseEmitter.event()
                                            .name("rewrite")
                                            .data(jsonData));
                                        Thread.sleep(200); // 增加延迟
                                        break;
                                    case "selector":
                                        // 发送选择器事件
                                        emitter.send(SseEmitter.event()
                                            .name("selector")
                                            .data(jsonData));
                                        Thread.sleep(200); // 增加延迟
                                        break;
                                    case "evidence":
                                        // 发送证据事件
                                        emitter.send(SseEmitter.event()
                                            .name("evidence")
                                            .data(jsonData));
                                        Thread.sleep(200); // 增加延迟
                                        break;
                                    case "sql_part":
                                        // 发送SQL部分事件，实现SQL的流式显示
                                        emitter.send(SseEmitter.event()
                                            .name("sql_part")
                                            .data(jsonData));
                                        // 增加SQL部分的延迟以实现更好的流式效果
                                        Thread.sleep(150);
                                        break;
                                    case "sql_comment":
                                        // 发送SQL注释事件
                                        emitter.send(SseEmitter.event()
                                            .name("sql_comment")
                                            .data(jsonData));
                                        Thread.sleep(150);
                                        break;
                                    case "sql":
                                        // 发送完整SQL事件
                                        emitter.send(SseEmitter.event()
                                            .name("sql")
                                            .data(jsonData));
                                        Thread.sleep(300); // SQL完成后稍长延迟
                                        break;
                                    case "sql_data":
                                        // 发送SQL数据事件
                                        emitter.send(SseEmitter.event()
                                            .name("sql_data")
                                            .data(jsonData));
                                        Thread.sleep(300); // 数据加载后稍长延迟
                                        break;
                                    case "result":
                                        // 发送结果事件，这里可能包含最终的文本
                                        if (innerData.containsKey("visualization")) {
                                            JSONObject visualization = innerData.getJSONObject("visualization");
                                            if (visualization.containsKey("text")) {
                                                String text = visualization.getStr("text");
                                                if (text != null && text.length() > 0) {
                                                    // 实现文本的打字机效果
                                                    implementTypingEffectForText(text, emitter, innerData);
                                                } else {
                                                    // 如果没有文本，直接发送原始数据
                                                    emitter.send(SseEmitter.event()
                                                        .name("result")
                                                        .data(jsonData));
                                                }
                                            } else {
                                                emitter.send(SseEmitter.event()
                                                    .name("result")
                                                    .data(jsonData));
                                            }
                                        } else {
                                            emitter.send(SseEmitter.event()
                                                .name("result")
                                                .data(jsonData));
                                        }
                                        // result事件不需要额外延迟，因为打字机效果已经包含延迟
                                        break;
                                    default:
                                        // 其他事件直接转发
                                        emitter.send(SseEmitter.event()
                                            .name(event)
                                            .data(jsonData));
                                        Thread.sleep(100); // 默认延迟
                                        break;
                                }
                            }
                        }
                        
                    } catch (Exception e) {
                        log.debug("解析JSON失败: {}", e.getMessage());
                    }
                }
            }
            
            if (hasValidData) {
                emitter.complete();
                return true;
            }
            
        } catch (Exception e) {
            log.error("真正的流式传输失败", e);
        }
        
        return false;
    }
    
    /**
     * 为文本实现打字机效果
     */
    private void implementTypingEffectForText(String text, SseEmitter emitter, JSONObject originalData) {
        try {
            StringBuilder currentText = new StringBuilder();
            int charsPerBatch = 5; // 改为每次发送1个字符，更平滑
            int delayMs = 10; // 增加延迟到120毫秒，更慢的打字机效果
            

            
            for (int i = 0; i < text.length(); i += charsPerBatch) {
                int endIndex = Math.min(i + charsPerBatch, text.length());
                String batch = text.substring(i, endIndex);
                currentText.append(batch);
                
                // 构造中间结果数据
                JSONObject progressData = new JSONObject();
                JSONObject data = new JSONObject();
                data.putAll(originalData);
                
                // 更新visualization中的text为当前文本
                JSONObject visualization = data.getJSONObject("visualization");
                if (visualization == null) {
                    visualization = new JSONObject();
                    data.put("visualization", visualization);
                }
                visualization.put("text", currentText.toString());
                
                // 添加进度标识
                data.put("event", "text_progress");
                progressData.put("data", data);
                
                // 发送进度数据
                emitter.send(SseEmitter.event()
                    .name("text_progress")
                    .data(progressData.toString()));
                
                // 延迟，但对标点符号稍作调整
                if (endIndex < text.length()) {
                    // 如果当前字符是标点符号，延迟稍长一些
                    char currentChar = text.charAt(endIndex - 1);
                    if (currentChar == '，' || currentChar == '。' || currentChar == '！' || currentChar == '？' || 
                        currentChar == '；' || currentChar == '：' || currentChar == '、') {
                        Thread.sleep(delayMs + 100); // 标点符号后多停顿100毫秒
                    } else {
                        Thread.sleep(delayMs);
                    }
                }
            }
            
            // 发送最终结果
            JSONObject finalData = new JSONObject();
            JSONObject finalInnerData = new JSONObject();
            finalInnerData.putAll(originalData);
            finalInnerData.put("event", "result");
            finalData.put("data", finalInnerData);
            
            Thread.sleep(100); // 在发送最终结果前稍作停顿
            emitter.send(SseEmitter.event()
                .name("result")
                .data(finalData.toString()));
                
        } catch (Exception e) {
            log.error("文本打字机效果失败", e);
        }
    }
    
    /**
     * 从流式数据中提取最终的完整文本内容
     */
    private String extractFinalTextContent(String streamData) {
        try {
            // 按行分割
            String[] lines = streamData.split("\n");
            
            for (String line : lines) {
                if (line.startsWith("data:")) {
                    String jsonData = line.substring(5);
                    try {
                        JSONObject data = JSONUtil.parseObj(jsonData);
                        
                        // 检查是否有data字段
                        if (data.containsKey("data")) {
                            JSONObject innerData = data.getJSONObject("data");
                            
                            // 检查是否是result事件
                            if ("result".equals(innerData.getStr("event"))) {
                                // 检查是否有visualization字段
                                if (innerData.containsKey("visualization")) {
                                    JSONObject visualization = innerData.getJSONObject("visualization");
                                    if (visualization.containsKey("text")) {
                                        String text = visualization.getStr("text");
                                        if (text != null && text.length() > 0) {
                                            log.info("成功提取到最终文本内容，长度: {}", text.length());
                                            return text;
                                        }
                                    }
                                }
                            }
                        }
                        
                    } catch (Exception e) {
                        log.debug("解析JSON失败: {}", e.getMessage());
                    }
                }
            }
            
            log.warn("未找到有效的文本内容");
            return null;
            
        } catch (Exception e) {
            log.error("提取文本内容失败", e);
            return null;
        }
    }
    
    /**
     * 原始流式数据转发（备用方案）
     */
    private void forwardOriginalStreamData(String streamData, SseEmitter emitter) {
        try {
            String[] lines = streamData.split("\n");
            
            for (String line : lines) {
                if (line.startsWith("data:")) {
                    String jsonData = line.substring(5);
                    emitter.send(SseEmitter.event().data(jsonData));
                } else if (line.startsWith("event:")) {
                    String eventName = line.substring(6);
                    emitter.send(SseEmitter.event().name(eventName));
                }
            }
            
            emitter.complete();
            log.info("✅ 原始流式数据转发完成");
            
        } catch (Exception e) {
            log.error("原始流式数据转发失败", e);
            try {
                emitter.completeWithError(e);
            } catch (Exception ex) {
                log.error("完成错误状态失败", ex);
            }
        }
    }
} 